#pragma once

#include <iostream>
#include <jsoncpp/json/json.h>

#include "compile.hpp"
#include "runner.hpp"
#include "../comm/log.hpp"
#include "../comm/util.hpp"

namespace ns_compile_and_run
{
    using namespace ns_logUtil;
    using namespace ns_util;
    using namespace ns_compile;
    using namespace ns_runner;
    class CompileAndRun
    {
    public:
        static void RemoveTempFile(const std::string &file_name)
        {
            if(FileUtil::IsFileExists(PathUtil::Src(file_name)))
                unlink(PathUtil::Src(file_name).c_str());

            if(FileUtil::IsFileExists(PathUtil::Exe(file_name)))
                unlink(PathUtil::Exe(file_name).c_str());

            if( FileUtil::IsFileExists(PathUtil::Compile_Error(file_name)) )
                unlink(PathUtil::Compile_Error(file_name).c_str());

            if(FileUtil::IsFileExists(PathUtil::StdIn(file_name)))
                unlink(PathUtil::StdIn(file_name).c_str());

            if(FileUtil::IsFileExists(PathUtil::StdOut(file_name)))
                unlink(PathUtil::StdOut(file_name).c_str());

            if(FileUtil::IsFileExists(PathUtil::StdErr(file_name)))
                unlink(PathUtil::StdErr(file_name).c_str());
        }

        static std::string CodeToReason(int code, const  std::string &_file_name)
        {
            std::string reason;
            switch(code)
            {
                case 0:
                    reason = "编译运行成功";
                    break;
                case -1:
                    reason = "提交的代码为空";
                    break;
                case -2:
                    reason = "未知错误(内部错误)";
                    break;
                case -3:
                    FileUtil::ReadFile(PathUtil::Compile_Error(_file_name), &reason); // 编译错误；
                    break;
                // 运行错误放进stderr文件中，不以reason传出
                // case -4:
                //     reason = FileUtil::ReadFile(PathUtil::StdErr(file_name), &reason, true);
                //     break;
                 case SIGABRT: // 6
                    reason = "内存超过范围";
                    break;
                case SIGXCPU: // 24
                    reason = "CPU使用超时";
                    break;
                case SIGFPE: // 8
                    reason = "浮点数溢出";
                    break;
                default:
                    reason = "未知: " + std::to_string(code);
                    break;
            }

            return reason;
        }


        /***************************
        *   status = -1 : 代码为空；
        *   status = -2 : 未知错误（代码内部错误）
        *   status = -3 : 编译错误
        *   status = -4 ： 运行错误  
        *
        ********************************/
        static void Start(const std::string &in_json, std::string *out_json)
        {
            Json::Value in_value;
            Json::Reader reader;
            reader.parse(in_json, in_value);
            // Debug
            //std::cout << "11cpu: "<<  in_value["cpu_limit"] << "mem :"<<  in_value["mem_limit"] << std::endl;
            
            std::string code = in_value["code"].asString();
            std::string input = in_value["input"].asString();
            // // Debug
            // std::cout << "debug7 " <<  "nijao" <<  std::endl;
            int cpu_limit = atoi(in_value["cpu_limit"].asString().c_str());
            // // Debug
            // std::cout << "debug8" << std::endl;
            int mem_limit = atoi(in_value["mem_limit"].asString().c_str());

            // // Debug
            // std::cout << "debug6" << std::endl;
            Json::Value out_value;
            int status_code = 0;
            int run_result = 0;
            std::string _file_name;
            if(code.size() == 0)
            {
                // 代码为空
                status_code = -1;
                goto END;
            }
            // // Debug
            // std::cout << "debug7" << std::endl;
            // 形成的文件具有唯一性，没有目录没有后缀
            _file_name = FileUtil::UniqFileName();

            // 将代码写入唯一文件中
            if( !FileUtil::WriteFile(PathUtil::Src(_file_name), code) )
            {
                status_code = -2;
                goto END;
            }
            
            // 编译运行
            if(!Compiler::Compile(_file_name))
            {
                // 编译错误
                status_code = -3;
                goto END;
            }

        /*        Run返回值：
        *       > 0 : 目标exe源文件发生错误
        *       == 0 ： 运行成功
        *       < 0 : 未知错误（代码内部错误）
        */
            run_result = Runner::Run(_file_name, cpu_limit, mem_limit);
            if(run_result > 0)
            {
                status_code = run_result;
            }
            else if(run_result < 0)
            {
                // 运行错误
                status_code = -4;
            }
            else
            {
                // 运行成功
                status_code = 0;

            }
            END:
            out_value["status"] = status_code;
            out_value["reason"] = CodeToReason(status_code, _file_name);

            if(status_code == 0)
            {
                // 编译运行成功
                std::string _stdout_json;
                std::string _stderr_json;

                if(FileUtil::ReadFile(PathUtil::StdOut(_file_name), &_stdout_json, true) 
                || FileUtil::ReadFile(PathUtil::StdErr(_file_name), &_stderr_json, true))
                {
                    status_code = -2; // 未知错误
                }

                out_value["stdout"] = _stdout_json;
                out_value["stderr"] = _stderr_json;
            }
            Json::StyledWriter writer;
            (*out_json) = writer.write(out_value);

            // 清理temp目录下的临时文件
            RemoveTempFile(_file_name);
            
        }
    };
}